package com.ebo.storage.redis;

import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;

public class JRedisFactory {
	
	private int virtual_shards;
	private String masterUrls;
	private String passwords;
	private int timeBetweenEvictionRunsMillis = 60000;
    private int minEvictableIdleTimeMillis = 60000;
    private int numTestsPerEvictionRun = 10;
    private int maxActive = 400;
    private int maxIdle = 10;
    private int minIdle = 4;
    private int maxWait = GenericObjectPool.WHEN_EXHAUSTED_GROW;
    private boolean testWhileIdle = true;
    private boolean testOnBorrow = false;
    private boolean testOnReturn = false;
	
	private ShardingAlgorithm shardingPools;

	public JRedisFactory() {
		super();
	}

	public JRedisFactory(int virtual_shards, String masterUrls, String passwords, int timeBetweenEvictionRunsMillis,
			int minEvictableIdleTimeMillis, int numTestsPerEvictionRun, int maxActive, int maxIdle, int minIdle,
			int maxWait, boolean testWhileIdle, boolean testOnBorrow, boolean testOnReturn) {
		super();
		this.virtual_shards = virtual_shards;
		this.masterUrls = masterUrls;
		this.passwords = passwords;
		this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
		this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
		this.numTestsPerEvictionRun = numTestsPerEvictionRun;
		this.maxActive = maxActive;
		this.maxIdle = maxIdle;
		this.minIdle = minIdle;
		this.maxWait = maxWait;
		this.testWhileIdle = testWhileIdle;
		this.testOnBorrow = testOnBorrow;
		this.testOnReturn = testOnReturn;
	}

	public JRedisFactory(int virtual_shards, String masterUrls, String passwords) {
		this.virtual_shards = virtual_shards;
		this.masterUrls = masterUrls;
		this.passwords = passwords;
		this.shardingPools = createAlgo();
	}
	
	public void init() {
		this.shardingPools = createAlgo();
	}

	 /**
     * @param masterUrls  nodeName1:host:port,nodeName2:host:port
     * @param slaveUrls   host:port,host:port
     * @return
     */
    public JRedis createJRedis(){
		System.out.println("#JRedisFactory creator JRedisProxy!");
        return new JRedisProxy(this.shardingPools);
    }

    private ShardingAlgorithm createAlgo() {
        String[] masters = masterUrls.split(",");
        String[] keys = passwords.split(",");
        
        Config config = this.initConfig();
        
        ShardedRedisPool[] pools = new ShardedRedisPool[masters.length];
        for (int idx=0; idx<masters.length; idx++) {
            String[] splitted = masters[idx].split(":");
            if (splitted.length != 3) {
                throw new IllegalArgumentException(masters[idx] + " is not a valid redis server address");
            }
            
            RedisShardInfo info = new RedisShardInfo(splitted[0], splitted[1], Integer.parseInt(splitted[2]));
            pools[idx] = new ShardedRedisPool(config, info, keys[idx]);
        }
        this.shardingPools = new ShardingAlgorithm(pools, virtual_shards);
        return this.shardingPools;
    }
    
    public ShardedRedisPool[] getPools() {
    	return this.shardingPools.getPools();
    }
    
    /**
     * @return
     */
    private Config initConfig() {
        Config config = new Config();
        config.timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;
        config.minEvictableIdleTimeMillis = this.minEvictableIdleTimeMillis;
        config.numTestsPerEvictionRun = this.numTestsPerEvictionRun;
        config.maxActive = this.maxActive;
        config.maxIdle = this.maxIdle;
        config.minIdle = this.minIdle;
        config.maxWait = GenericObjectPool.WHEN_EXHAUSTED_GROW;
        config.testWhileIdle = this.testWhileIdle;
        config.testOnBorrow = this.testOnBorrow;
        config.testOnReturn = this.testOnReturn;
        return config;
    }

	public int getTimeBetweenEvictionRunsMillis() {
		return timeBetweenEvictionRunsMillis;
	}

	public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
		this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
	}

	public int getMinEvictableIdleTimeMillis() {
		return minEvictableIdleTimeMillis;
	}

	public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
		this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
	}

	public int getNumTestsPerEvictionRun() {
		return numTestsPerEvictionRun;
	}

	public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
		this.numTestsPerEvictionRun = numTestsPerEvictionRun;
	}

	public int getMaxActive() {
		return maxActive;
	}

	public void setMaxActive(int maxActive) {
		this.maxActive = maxActive;
	}

	public int getMaxIdle() {
		return maxIdle;
	}

	public void setMaxIdle(int maxIdle) {
		this.maxIdle = maxIdle;
	}

	public int getMinIdle() {
		return minIdle;
	}

	public void setMinIdle(int minIdle) {
		this.minIdle = minIdle;
	}

	public int getMaxWait() {
		return maxWait;
	}

	public void setMaxWait(int maxWait) {
		this.maxWait = maxWait;
	}

	public boolean isTestWhileIdle() {
		return testWhileIdle;
	}

	public void setTestWhileIdle(boolean testWhileIdle) {
		this.testWhileIdle = testWhileIdle;
	}

	public boolean isTestOnBorrow() {
		return testOnBorrow;
	}

	public void setTestOnBorrow(boolean testOnBorrow) {
		this.testOnBorrow = testOnBorrow;
	}

	public boolean isTestOnReturn() {
		return testOnReturn;
	}

	public void setTestOnReturn(boolean testOnReturn) {
		this.testOnReturn = testOnReturn;
	}

	public ShardingAlgorithm getShardingPools() {
		return shardingPools;
	}

	public void setShardingPools(ShardingAlgorithm shardingPools) {
		this.shardingPools = shardingPools;
	}

	public int getVirtual_shards() {
		return virtual_shards;
	}

	public void setVirtual_shards(int virtual_shards) {
		this.virtual_shards = virtual_shards;
	}

	public String getMasterUrls() {
		return masterUrls;
	}

	public void setMasterUrls(String masterUrls) {
		this.masterUrls = masterUrls;
	}

	public String getPasswords() {
		return passwords;
	}

	public void setPasswords(String passwords) {
		this.passwords = passwords;
	}
}
